{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from pprint import pprint as p"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 当元阵列是一维时，结果的形状就等于索引阵列的形状\n",
    "a = np.random.randint(10,size=5)\n",
    "idx = np.array([[0,3,1],[2,1,3]])\n",
    "r = a[idx]\n",
    "p(r)\n",
    "p([a.shape, idx.shape, r.shape])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 当元阵列是多维时，结果的形状的前面部分等于索引阵列的形状\n",
    "a = np.random.randint(10,size=(5,7))\n",
    "idx = np.array([[0,3,1],[2,1,3]])\n",
    "r = a[idx]\n",
    "p(a)\n",
    "print('-'*30)\n",
    "p(r)\n",
    "p([a.shape, idx.shape, r.shape])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 当元阵列是多维时，结果的形状的前面部分等于索引阵列的形状\n",
    "a = np.random.randint(10,size=(5,5,4,3,2))\n",
    "idx = np.array([[0,3,1],[2,1,3]])\n",
    "r = a[idx]\n",
    "p([a.shape, idx.shape, r.shape])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 使用多个索引阵列\n",
    "#### 1. 所有用来做索引的阵列形状必须相同\n",
    "#### 2. 如果形状不同，将会尝试广播\n",
    "#### 3. 如果不能广播，就失败\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.arange(7)\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 当用了多个阵列做索引时，就是多个index了，这个时候就要求原阵列有足够的维数\n",
    "# 所以，以下语句会出错\n",
    "# a[[0,1], [3,5]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = np.arange(35).reshape(5,7)\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 多个索引阵列对应位置上的数字组合成位置，用来索引原阵列中的一个元素\n",
    "# 因此 [0,1]和[3,5] 最终组合成 (0,3), (1,5) 这两个位置\n",
    "a[[0,1], [3,5]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a[[0,1,2,3],[6,5,4,3]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# a[[0,1,2,3],[6,5,4]]  # 两个索引阵列形状不兼容广播，将会出错\n",
    "a[[0,1,2,3],[6]]        # 两个索引阵列形状可以广播，等价于 [0,1,2,3],[6,6,6,6]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 原阵列的轴数必须不小于索引阵列的总数量\n",
    "a = np.zeros((5,5,5,5))\n",
    "a[[0,1],[1,2],[1,2]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 数字和索引阵列一起使用，数字在前面，阵列在后面\n",
    "a = np.arange(60).reshape(3,4,5)\n",
    "p(a)\n",
    "p(a[2,[1,2]])\n",
    "p(a[[2,2],[1,2]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 多个数字和阵列一起使用，数字在左边\n",
    "p(a)\n",
    "a[1,2,[2,3,4]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 数字和阵列一起使用，数字在右边\n",
    "# 按顺序抽取原阵列里面对应轴上的元素\n",
    "p(a)\n",
    "p(a[[0,1],2])\n",
    "p(a[[0,1],[2,2]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "p(a[[0,1],2,1])\n",
    "p(a[[0,1],[2,2],[1,1]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "p(a)\n",
    "# p(a[:2,1])\n",
    "p(a[1,:2])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "p(a)\n",
    "p(a[:2,[0,2]])\n",
    "p(a[[0,2],:2])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# p(a[[0,1]])\n",
    "# idx = np.array([0,1])\n",
    "# p(a[idx])\n",
    "\n",
    "# 当用多维阵列时，需要注意，元组的行为比较特殊\n",
    "p(a)\n",
    "# p(a[ [[0,1], [0,1]] ])\n",
    "# p(a[ ((0,1), (0,1)) ])\n",
    "\n",
    "# 为了确保所写的索引是有效的，可以生成np.ndarray类型的阵列\n",
    "# idx = np.array([[0,1],[1,2]])\n",
    "\n",
    "p(a[[0,1]])\n",
    "p(a[(0,1)])\n",
    "p(a[0,1])"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
